package org.hang.gift.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.hang.exception.BusinessException;
import org.hang.exception.ResponseCode;
import org.hang.exception.RonghuaAssert;
import org.hang.gift.clients.AuthClient;
import org.hang.gift.constants.UserConstants;
import org.hang.gift.domain.LoginUser;
import org.hang.gift.domain.User;

import org.hang.gift.domain.UserInfo;
import org.hang.gift.dto.UserRegDto;
import org.hang.gift.mapper.UserInfoMapper;
import org.hang.gift.mapper.UserMapper;
import org.hang.gift.service.IUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.hang.util.AjaxResult;
import org.hang.util.VerifyCodeUtils;
import org.hang.util.encrypt.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author hang
 * @since 2024-05-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

   @Autowired
   private UserMapper userMapper;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private AuthClient authClient;


    /**
     * @GlobalTransactional 开启全局事务
     * @param dto
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(UserRegDto dto) {
     //1.验证用户输入的信息不为空  JSR303验证属性不为空
        //手机号是否注册过
        User user1 =super.selectOne(new EntityWrapper<User>().eq("phone",dto.getPhone()));
        RonghuaAssert.isNull(user1, ResponseCode.RESPONSE_CODE_400009);

        //2.验证 手机验证码是否正确
      String phone = dto.getPhone();
      String key = UserConstants.USER_REGISTER_SEND_SMS_KEY+"-"+phone;
      String codeInRedisStr = (String)redisTemplate.opsForValue().get(key);
      //2.1 如果从redis中取出数据为空，表示验证码过期，报异常
      RonghuaAssert.isNotBlank(codeInRedisStr, ResponseCode.RESPONSE_CODE_400013);
        String code = codeInRedisStr.split(":")[0];
        //为了少出现异常，第一个参数应该写确定不为空的
      RonghuaAssert.isEq(dto.getPhoneCode(),code,ResponseCode.RESPONSE_CODE_400013);

      //3.密码 加密加盐处理
        //替换横线
        String salt = UUID.randomUUID().toString().replaceAll("-","");
        // 为了增加安全性，防止暴力破解，我们可以在代码中，在salt+password前后输入一些固定的字符串
        String password = MD5.getMD5("hang"+salt+dto.getPassword()+"test");

        //4. 将数据存到认证授权服务的用户登录信息表 login_user 并返回login_id
        LoginUser loginUser = new LoginUser();
        //用户注册时，没有输入用户名,所以先随机生成一个字符串作为用户名
        loginUser.setUsername(UUID.randomUUID().toString());
        loginUser.setSalt(salt);
        loginUser.setPassword(password);
        loginUser.setPhone(dto.getPhone());
        loginUser.setType(1);
        AjaxResult ajaxResult = authClient.addOrUpdate(loginUser);
        if(!ajaxResult.isSuccess()){
            //远程调用授权服务保存登录信息,有可能会报错不成功,如果报错我们就抛出异常,阻止程序继续往下运行
            throw new BusinessException(ajaxResult.getMessage());
        }

        Long loginId = Long.valueOf(ajaxResult.getResultObj().toString());

      //5.1将数据存到用户表 user
        User user = new User();
        user.setCreateTime(new Date().getTime());
        user.setPhone(dto.getPhone());
        user.setPassword(password);
        user.setSalt(salt);
        user.setBitState(1L);
        user.setSecLevel(1);
        user.setLoginId(loginId);
        insert(user);

      //5.2 将数据存到用户信息表 userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setRegTime(new Date().getTime());
        userInfo.setLevel(0);
        userInfo.setGrowScore(0);
        userInfo.setUserId(user.getId());
        userInfoMapper.insert(userInfo);

        //6,给用户发送注册成功的邮件或 短信通知 消息队列
        System.out.println("注册成功");
        //System.out.println(1/0);

    }
}
